#ifndef _core_switch_detail_value_of_impl_hpp_
#define _core_switch_detail_value_of_impl_hpp_

/** \file value_of_impl.hpp
 *  \author Adrian Schweizer
 *  \created  $Mo 11 Feb 08:33:01 pm CET 2008 schwadri@SchwadriLaptop.local$
 *  \modified $Mo 11 Feb 08:40:25 pm CET 2008 schwadri@SchwadriLaptop.local$
 */

#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/void.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/at.hpp>

namespace core {

    struct case_iterator_tag;

    template <typename C, std::size_t P>
        struct case_iterator;
}

namespace boost {
    namespace fusion {
        namespace extension {

            template <typename Tag>
                struct value_of_impl;

            template <>
                struct value_of_impl<core::case_iterator_tag>
                {
                    /*reached end of this case. look if we need to go to the next one*/
                    template <typename F, typename N, std::size_t S, std::size_t P>
                        struct eval_impl
                        :   mpl::eval_if_c<
                                (P < S),
                                mpl::identity<pair<typename mpl::at_c<typename F::labels,P>::type,F> >,
                                eval_impl<typename N::functor, typename N::next,mpl::size<typename N::labels>::value,P-S>
                                >
                        { };

                    template <typename F, std::size_t S, std::size_t P>
                        struct eval_impl<F,mpl::void_,S,P>
                        :   mpl::eval_if_c<
                                (P < S),
                                mpl::identity<pair<typename mpl::at_c<typename F::labels,P>::type,F> >,
                                mpl::identity<mpl::void_>
                                >
                        { };

                    template <typename Iterator>
                        struct apply;

                    template <typename Case, std::size_t Pos>
                        struct apply<core::switch_case_iterator<Case,Pos> >
                        :   eval_impl<typename Case::functor,
                                        typename Case::next,
                                        mpl::size<typename Case::labels>::value,
                                        Pos>
                        { };
            };
        }
    }
}


#endif // _core_switch_detail_value_of_impl_hpp_
